import QRCode from 'qrcode';
import React, { useEffect, useRef, useState } from 'react';
import { useTranslation } from 'react-i18next';

import { MobileLoginErrorCode } from '@/entrypoints/popup/types/MobileLoginErrorCode';
import { MobileLoginUtility } from '@/entrypoints/popup/utils/MobileLoginUtility';

import type { MobileLoginResult } from '@/utils/types/messaging/MobileLoginResult';
import type { WebApiService } from '@/utils/WebApiService';

interface IMobileUnlockModalProps {
  isOpen: boolean;
  onClose: () => void;
  onSuccess: (result: MobileLoginResult) => Promise<void>;
  webApi: WebApiService;
  mode?: 'login' | 'unlock';
}

/**
 * Modal component for mobile login/unlock via QR code scanning.
 */
const MobileUnlockModal: React.FC<IMobileUnlockModalProps> = ({
  isOpen,
  onClose,
  onSuccess,
  webApi,
  mode = 'login'
}) => {
  const { t } = useTranslation();
  const [qrCodeUrl, setQrCodeUrl] = useState<string | null>(null);
  const [error, setError] = useState<MobileLoginErrorCode | null>(null);
  const [timeRemaining, setTimeRemaining] = useState<number>(120); // 2 minutes in seconds
  const mobileLoginRef = useRef<MobileLoginUtility | null>(null);
  const countdownIntervalRef = useRef<NodeJS.Timeout | null>(null);

  /**
   * Get translated error message for error code.
   */
  const getErrorMessage = (errorCode: MobileLoginErrorCode): string => {
    switch (errorCode) {
      case MobileLoginErrorCode.TIMEOUT:
        return t('auth.errors.mobileLoginRequestExpired');
      case MobileLoginErrorCode.GENERIC:
      default:
        return t('common.errors.unknownError');
    }
  };

  // Countdown timer effect
  useEffect(() => {
    if (qrCodeUrl && timeRemaining > 0 && isOpen) {
      countdownIntervalRef.current = setInterval(() => {
        setTimeRemaining(prev => {
          if (prev <= 1) {
            if (countdownIntervalRef.current) {
              clearInterval(countdownIntervalRef.current);
            }
            return 0;
          }
          return prev - 1;
        });
      }, 1000);

      return (): void => {
        if (countdownIntervalRef.current) {
          clearInterval(countdownIntervalRef.current);
        }
      };
    }
  }, [qrCodeUrl, timeRemaining, isOpen]);

  // Initialize mobile login when modal opens
  useEffect(() => {
    if (!isOpen) {
      return;
    }

    /**
     * Initialize mobile login on modal open.
     */
    const initiateMobileLogin = async (): Promise<void> => {
      try {
        setError(null);
        setQrCodeUrl(null);
        setTimeRemaining(120);

        // Initialize mobile login utility
        if (!mobileLoginRef.current) {
          mobileLoginRef.current = new MobileLoginUtility(webApi);
        }

        // Initiate mobile login and get QR code data
        const requestId = await mobileLoginRef.current.initiate();

        // Generate QR code with AliasVault prefix for mobile login
        const qrData = `aliasvault://open/mobile-unlock/${requestId}`;
        const qrDataUrl = await QRCode.toDataURL(qrData, {
          width: 256,
          margin: 2,
        });

        setQrCodeUrl(qrDataUrl);

        // Start polling for response
        await mobileLoginRef.current.startPolling(
          async (result: MobileLoginResult) => {
            try {
              // Call success callback (parent handles loading state)
              await onSuccess(result);
              // Close modal after successful processing
              handleClose();
            } catch {
              // Show error if success handler fails and hide QR code
              setQrCodeUrl(null);
              setError(MobileLoginErrorCode.GENERIC);
            }
          },
          (errorCode) => {
            // Hide QR code when error occurs
            setQrCodeUrl(null);
            setError(errorCode);
          }
        );
      } catch (err) {
        // err is a MobileLoginErrorCode thrown by initiate()
        if (typeof err === 'string' && Object.values(MobileLoginErrorCode).includes(err as MobileLoginErrorCode)) {
          setError(err as MobileLoginErrorCode);
        } else {
          setError(MobileLoginErrorCode.GENERIC);
        }
      }
    };

    initiateMobileLogin();

    // Cleanup on unmount or when modal closes
    return (): void => {
      if (mobileLoginRef.current) {
        mobileLoginRef.current.cleanup();
      }
      if (countdownIntervalRef.current) {
        clearInterval(countdownIntervalRef.current);
      }
    };
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [isOpen]);

  /**
   * Handle modal close.
   */
  const handleClose = (): void => {
    if (mobileLoginRef.current) {
      mobileLoginRef.current.cleanup();
    }
    if (countdownIntervalRef.current) {
      clearInterval(countdownIntervalRef.current);
    }
    setQrCodeUrl(null);
    setError(null);
    setTimeRemaining(120);
    onClose();
  };

  /**
   * Format time remaining as MM:SS.
   */
  const formatTime = (seconds: number): string => {
    const mins = Math.floor(seconds / 60);
    const secs = seconds % 60;
    return `${mins}:${secs.toString().padStart(2, '0')}`;
  };

  if (!isOpen) {
    return null;
  }

  const title = mode === 'unlock' ? t('auth.unlockWithMobile') : t('auth.loginWithMobile');
  const description = t('auth.scanQrCode');

  return (
    <div className="fixed inset-0 z-50 overflow-y-auto">
      {/* Backdrop */}
      <div className="fixed inset-0 bg-black bg-opacity-80 transition-opacity" onClick={handleClose} />

      {/* Modal */}
      <div className="fixed inset-0 flex items-center justify-center p-4">
        <div className="relative transform overflow-hidden rounded-lg bg-white dark:bg-gray-800 px-6 pb-6 pt-5 text-left shadow-xl transition-all w-full max-w-md">
          {/* Close button */}
          <button
            type="button"
            className="absolute right-4 top-4 text-gray-400 hover:text-gray-500 focus:outline-none"
            onClick={handleClose}
          >
            <span className="sr-only">{t('common.close')}</span>
            <svg className="h-6 w-6" fill="none" viewBox="0 0 24 24" strokeWidth="1.5" stroke="currentColor">
              <path strokeLinecap="round" strokeLinejoin="round" d="M6 18L18 6M6 6l12 12" />
            </svg>
          </button>

          {/* Content */}
          <div className="mt-3">
            <h3 className="text-xl font-bold text-gray-900 dark:text-white mb-2">
              {title}
            </h3>
            <p className="text-sm text-gray-600 dark:text-gray-400 mb-4">
              {description}
            </p>

            {error && (
              <div className="mb-4 p-3 bg-red-100 dark:bg-red-900/30 border border-red-400 dark:border-red-700 rounded text-red-700 dark:text-red-400 text-sm">
                {getErrorMessage(error)}
              </div>
            )}

            {qrCodeUrl && (
              <div className="flex flex-col items-center mb-4">
                <img src={qrCodeUrl} alt="QR Code" className="border-4 border-gray-200 dark:border-gray-600 rounded mb-3" />
                <div className="text-gray-700 dark:text-gray-300 text-sm font-medium">
                  {formatTime(timeRemaining)}
                </div>
              </div>
            )}

            {!qrCodeUrl && !error && (
              <div className="flex justify-center py-8">
                <div className="animate-spin rounded-full h-12 w-12 border-b-2 border-primary-600"></div>
              </div>
            )}

            <button
              type="button"
              onClick={handleClose}
              className="mt-4 w-full inline-flex justify-center rounded-md bg-white dark:bg-gray-700 px-3 py-2 text-sm font-semibold text-gray-900 dark:text-gray-200 shadow-sm ring-1 ring-inset ring-gray-300 dark:ring-gray-600 hover:bg-gray-50 dark:hover:bg-gray-600 focus:outline-none focus:ring-2 focus:ring-primary-500"
            >
              {t('common.cancel')}
            </button>
          </div>
        </div>
      </div>
    </div>
  );
};

export default MobileUnlockModal;
